#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

vector<int> GetPrimes(int tar_sum) {
  const int kMaxPrime = 100000;
  bool not_prime[kMaxPrime] = {false};
  int primes[kMaxPrime / 10] = {0}, cnt = 0;

  for (int i = 2; i < kMaxPrime; i++) {
    if (!not_prime[i]) {
      primes[cnt++] = i;
    }
    for (int j = 0; j < cnt && i * primes[j] < kMaxPrime; j++) {
      not_prime[i * primes[j]] = true;
      if (i % primes[j] == 0) {
        break;
      }
    }
  }

  vector<int> ret;
  for (int prime : primes) {
    if (prime >= 10000) {
      int sum = 0;
      for (int x = prime; x; x /= 10) {
        sum += x % 10;
      }
      if (sum == tar_sum) {
        ret.emplace_back(prime);
      }
    }
  }
  return ret;
}

vector<vector<int>> Solve(const vector<int> &prime_list, int sum, int pos11) {
  vector<int> right_down_prime;
  vector<int> list[10][4][10000];

  for (int prime : prime_list) {
    list[prime / 10000][0][prime % 10].emplace_back(prime);
    list[prime / 10000][1][prime % 100].emplace_back(prime);
    list[prime / 10000][2][prime % 1000].emplace_back(prime);
    list[prime / 10000][3][prime % 10000].emplace_back(prime);
  }

  for (int prime : prime_list) {
    bool is_rd_prime = !list[pos11][0][prime / 10000].empty() && !list[pos11][0][prime % 10].empty();

    for (int x = prime; x && is_rd_prime; x /= 10) {
      switch (x % 10) {
        case 1:
        case 3:
        case 7:
        case 9:
          break;

        default:
          is_rd_prime = false;
          break;
      }
    }
    if (is_rd_prime) {
      right_down_prime.emplace_back(prime);
    }
  }

  vector<vector<int>> ret;
  auto Check = [&](int x, vector<int> y) {
    for (; x; x /= 10) {
      int r = 0;
      for (int &yy : y) {
        r = r * 10 + yy % 10;
        yy /= 10;
      }
      if (list[x % 10][y.size() - 1][r].empty()) {
        return false;
      }
    }
    return true;
  };
  auto GetNum = [&](int x, int len) {
    static int base[] = {1, 10, 100, 1000, 10000};

    return x / base[len] % 10;
  };
  for (int row5 : right_down_prime) {
    for (int col5 : right_down_prime) {
      int pos55 = GetNum(row5, 0);
      int pos15 = GetNum(col5, 4), pos51 = GetNum(row5, 4);
      if (pos55 != GetNum(col5, 0) || list[pos51][0][pos15].empty() || list[pos11][0][pos55].empty()) {  // Check pos55 & diagonals
        continue;
      }
      for (int row1 : list[pos11][0][pos15]) {
        if (!Check(row1, {row5})) {  // check col
          continue;
        }
        for (int col1 : list[pos11][0][pos51]) {
          if (!Check(col1, {col5})) {  // check row
            continue;
          }
          int pos14 = GetNum(row1, 1), pos54 = GetNum(row5, 1);
          for (int col4 : list[pos14][0][pos54]) {
            if (!Check(col1, {col4, col5})) {  // check row
              continue;
            }
            int pos24 = GetNum(col4, 3), pos44 = GetNum(col4, 1);
            if (list[pos51][1][pos24 * 10 + pos15].empty() || list[pos11][1][pos44 * 10 + pos55].empty()) {  // check diagonals
              continue;
            }

            int pos13 = GetNum(row1, 2), pos53 = GetNum(row5, 2);
            for (int col3 : list[pos13][0][pos53]) {
              if (Check(col1, {col3, col4, col5}) == false) {  // check row
                continue;
              }
              int rows[3] = {0};  // row2,row3,row4
              int sums[3] = {sum - GetNum(col1, 3), sum - GetNum(col1, 2), sum - GetNum(col1, 1)};

              for (int col : {col3 / 10, col4 / 10, col5 / 10}) {
                int id = 2;
                for (; col >= 10; col /= 10, id--) {
                  rows[id] *= 10;
                  rows[id] += col % 10;
                  sums[id] -= col % 10;
                }
              }

              for (int i = 0; i < 3; i++) {
                if (sums[i] < 0) {
                  continue;
                }
                rows[i] = GetNum(col1, 3 - i) * 10000 + sums[i] * 1000 + rows[i];
              }

              int col2 = GetNum(row1, 3) * 10000 + sums[0] * 1000 + sums[1] * 100 + sums[2] * 10 + GetNum(row5, 3);

              if (list[GetNum(row1, 3)][3][col2 % 10000].empty()) {  // check col2
                continue;
              }
              if (list[GetNum(rows[0], 4)][3][rows[0] % 10000].empty() ||
                  list[GetNum(rows[1], 4)][3][rows[1] % 10000].empty() ||
                  list[GetNum(rows[2], 4)][3][rows[2] % 10000].empty()) {  // check row2...4
                continue;
              }
              if (list[pos11][3][GetNum(col2, 3) * 1000 + GetNum(col3, 2) * 100 + pos44 * 10 + pos55].empty() ||
                  list[pos51][3][GetNum(col2, 1) * 1000 + GetNum(col3, 2) * 100 + pos24 * 10 + pos15].empty()) {
                continue;
              }
              ret.emplace_back(vector<int>{row1, rows[0], rows[1], rows[2], row5});
            }
          }
        }
      }
    }
  }
  return ret;
}

bool cmp(const vector<int> &a, const vector<int> &b) {
  for (int i = 0; i < 5; i++) {
    if (a[i] != b[i]) {
      return a[i] < b[i];
    }
  }
  return false;
}

int main() {
  // freopen("test.in", "r", stdin);
  // freopen("test.out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int sum, left_up_num;

  cin >> sum >> left_up_num;
  vector<int> prime_list = GetPrimes(sum);
  vector<vector<int>> res = Solve(prime_list, sum, left_up_num);
  sort(res.begin(), res.end(), cmp);
  for (int i = 0; i < res.size(); i++) {
    for (int prime : res[i]) {
      cout << prime << endl;
    }
    cout << endl;
  }
  return 0;
}